﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceProcess;
using SH_VBoxServiceTrayApp.WForms;
using System.Reflection;

using SH_VBoxLibrary;


namespace SH_VBoxServiceTrayApp
{

    /// <summary>
    /// Tray App Actual Class...
    /// Note: Need to make sure ONLY ONE of this Application is open at once.
    /// Also: This app doesnt matter if its closed. because it will only be needed to OPERATE the service
    /// as user friendly and not like the ONLY source of control over the service.
    /// So if the app its closed the Service will still be up ready and working.
    /// </summary>
    class TrayClass : ApplicationContext
    {




        #region Variables


        /// <summary>
        /// Service Name that this Tray app will control.
        /// </summary>
        string MyServiceName = @"VBoxTrinketService";
        
        /// <summary>
        /// A reference to the Service that this Tray app 
        /// will have control of.
        /// </summary>
        ServiceController serviceref = null;
        
        /// <summary>
        /// The Actual Tray Icon located on the TaskBar.
        /// </summary>
        NotifyIcon notifyIcon = null;

        //I Need this here to control the CheckMark if its actually checked or not.
        //Need to change this to a List if I will manage the seperate VM's from the Tray as well.
        MenuItem itemStartService = null;
        MenuItem itemStopService = null;
        MenuItem itemShowConfigWindow = null;
        MenuItem itemExit = null;



      
        /// <summary>
        /// Configuration Windows. 
        /// Needed to add or remove the VM's the Service will manage.
        /// Also to determine where the VBoxManage is located.
        /// </summary>
        private FormConfigOptions configWindow = null;



        #endregion




        public TrayClass()
        {
            //testing
            ConfigIO.readConfig();
            

           
            //Check first if the service has been actually installed... 
            //if not this Tray app has nothing else todo and it will shutdown.
            if (this.IsServiceInstalled(MyServiceName))
            {
                //proceed and get the service.
                serviceref = getService(MyServiceName);
            }
            else
            {
                serviceref = null;
                
                MessageBox.Show("VBoxTrinketService was not properly installed!\nVBoxTrinket can't start....", 
                                "Error Initiating VBoxTrinket!",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);
                
                this.Dispose();
                return;
            }

            
            //instantiating Config Window...All read From ConfigFile
            configWindow = new FormConfigOptions();
            configWindow.Hide();


            //Creating the Tray App Icon and Menu.
          
        
            this.itemStartService = new MenuItem("Start VBoxTrinketService", new EventHandler(StartVBoxService));
            itemStopService = new MenuItem("Stop VBoxTrinketService", new EventHandler(StopVBoxService));
            MenuItem itemFirstHLine = new MenuItem("-");
            itemShowConfigWindow = new MenuItem("Configuration...", new EventHandler(ShowConfig));
            itemShowConfigWindow.DefaultItem = true;
            MenuItem itemSecondHLine = new MenuItem("-");
            itemExit = new MenuItem("Exit", new EventHandler(Exit));

            notifyIcon = new NotifyIcon();
            notifyIcon.Icon = SH_VBoxServiceTrayApp.Properties.Resources.vboxtrinketicon_hd;
            //After Double Click it opens the Configuration Window Directly.
            notifyIcon.MouseDoubleClick += new MouseEventHandler(notifyIcon_MouseDoubleClick); 
            //adding the Menu items
            notifyIcon.ContextMenu = new ContextMenu(new MenuItem[] { itemStartService, 
                                                                      itemStopService,
                                                                      itemFirstHLine,
                                                                      itemShowConfigWindow,
                                                                      itemSecondHLine,
                                                                      itemExit });

            //Puts the check on the Status that is currently active.
            if (serviceref.Status == ServiceControllerStatus.Running)
            {
                itemStartService.Checked = true;
            }
            else if (serviceref.Status == ServiceControllerStatus.Stopped)
            {
                itemStopService.Checked = true;
            }


            notifyIcon.Visible = true;            
            notifyIcon.Text = "VBoxTrinketService Controller";
            
            //Change this if the Service was not correctly installed. 
            //to something like Error: Service App was not properly installed, try again.
            notifyIcon.BalloonTipIcon = ToolTipIcon.Info;
            notifyIcon.BalloonTipTitle = "VBoxTrinket Tray-Controller At Your Service!";
            notifyIcon.BalloonTipText = "Now you can manage all your VirtualBox's Virtual Machines from here!";
            notifyIcon.ShowBalloonTip(10000);

       
        }



        #region NotifyIcon Events

       /// <summary>
       /// This shows a Window that will help make all config options.
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
        void ShowConfig(object sender, EventArgs e)
        {
            //PreLoading the Data.
            configWindow.loadConfigData();

            // If we are already showing the window, merely focus it.
            if (configWindow.Visible)
            {
                configWindow.Activate();
            }
           else
           {
                configWindow.ShowDialog();  
           }
        }

        /// <summary>
        /// Starts the "VBoxTrinketService" Windows Service. 
        /// </summary>
        void StartVBoxService(object sender, EventArgs e)
        {
            if (serviceref.Status != ServiceControllerStatus.Running || 
                serviceref.Status != ServiceControllerStatus.StartPending ||
                serviceref.Status != ServiceControllerStatus.ContinuePending)
            {
                serviceref.Start();
                //helps me change the status to the desired one.
                //but it changes it gracefully, without affecting the service itself.
                serviceref.WaitForStatus(ServiceControllerStatus.Running);
                itemStartService.Checked = true;
                itemStopService.Checked = false;
            }
        }

        /// <summary>
        /// Stops the "VBoxTrinketService" Windows Service.
        /// </summary>
        void StopVBoxService(object sender, EventArgs e)
        {
            //Wait for the Service to actually start in order to be able to stop.
            if (serviceref.Status != ServiceControllerStatus.Stopped ||
                serviceref.Status != ServiceControllerStatus.StartPending ||
                serviceref.Status != ServiceControllerStatus.ContinuePending ||
                serviceref.Status != ServiceControllerStatus.StopPending)
            {
                serviceref.Stop();
                serviceref.WaitForStatus(ServiceControllerStatus.Stopped);
                itemStartService.Checked = false;
                itemStopService.Checked = true;
            }

        }


        /// <summary>
        /// Closes the Tray Application.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Exit(object sender, EventArgs e)
        {
            // We must manually tidy up and remove the icon before we exit.
            // Otherwise it will be left behind until the user mouses over.
            notifyIcon.Visible = false;
            Application.Exit();
        }


        /// <summary>
        /// Event is fired after a Double click.
        /// </summary>
        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            
            if (e.Button == MouseButtons.Left)
            {
                itemShowConfigWindow.PerformClick();
            }
               
        }


        #endregion


        #region PrivateMethods



        /// <summary>
        /// Just helps me check that the Service was actually installed 
        /// so that the tray app can be Opened successfully.
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        private bool IsServiceInstalled(string serviceName)
        {
            // get list of Windows services
            ServiceController[] services = ServiceController.GetServices();

            // try to find service name
            foreach (ServiceController service in services)
            {
                if (service.ServiceName == serviceName)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Helper methods, gets the actual service controller based on the name of the service.
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        private ServiceController getService(string serviceName)
        {
            ServiceController[] services = ServiceController.GetServices();

            // try to find service name
            foreach (ServiceController service in services)
            {
                if (service.ServiceName == serviceName)
                    return service;
            }
            return null;
        }


        #endregion

    }
}
